package client

import (
	"DB/HttpVPN/http"
	"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"strings"
)

const (
	dealDefaultRequestCount = 6
)

func httpHeaderModify(req *http.Request, host string) {
	req.Header.Set(http.Host, host)
}

type Client struct {
	clientConn       net.Conn
	dealRequestCount int
	dataBuffer       bytes.Buffer
	bufferReader     *bufio.Reader
	transponder      *Transponder
	responseChan     chan *http.Response
}

func (this *Client) readHttpHeader() *http.Request {
	req := http.CreateRequest()
	this.readStartLine(req)
	this.readHeader(req)

	if req.GetMethod() == http.POST {
		this.readBody(req)
	}
	httpHeaderModify(req, "www.baidu.com")
	fmt.Println(req)
	return req
}

func (this *Client) readBody(req *http.Request) {
	bodyLength := req.GetContentLength()
	bodyData := make([]byte, bodyLength)
	binary.Read(this.clientConn, binary.BigEndian, bodyData)
	req.Body.Write(bodyData)
}

func (this *Client) readHeader(req *http.Request) {
	for {
		httpLine := ""
		line, prefix, err := this.bufferReader.ReadLine()
		if err != nil {
			panic(err)
		}
		if len(line) == 0 {
			break
		}
		httpLine += string(line)
		if prefix != false {
			line, prefix, err = this.bufferReader.ReadLine()
			httpLine += string(line)
		}

		split := strings.Split(httpLine, ":")
		key := split[0]
		value := []byte(httpLine)

		tempValue := value[len(key)+2:]

		v := strings.Split(string(tempValue), ";")

		for i := 0; i < len(v); i++ {
			if i == 0 {
				req.Header.Set(key, v[i])
				continue
			}
			req.Header.Add(key, v[i])
		}
	}
}

func (this *Client) readStartLine(req *http.Request) {
	startLineByte, prefix, _ := this.bufferReader.ReadLine()
	startLine := string(startLineByte)
	defer func() {
		err := recover()
		fmt.Println(err)
	}()
	if prefix == true {
		for true {
			line, isPrefix, err := this.bufferReader.ReadLine()
			if err != nil {
				panic(err)
			}

			startLine += string(line)

			if isPrefix == false {
				break
			}
		}
	}

	split := strings.Split(startLine, " ")

	req.StartLine.Method = split[0]
	req.StartLine.URL = split[1]
	req.StartLine.Version = split[2]

}

func (this *Client) Serve() {
	//defer func() {
	//	if err := recover(); err != nil {
	//		fmt.Println("one connection exit")
	//	}
	//}()
	go this.repeatResponse()

	for {
		header := this.readHttpHeader()
		this.transponder.Repeat(header)
		fmt.Println(header)
	}
}

func (this *Client) repeatResponse() {
	for {
		respone := <-this.responseChan
		responseEncodeBytes := respone.Encode()
		this.clientConn.Write(responseEncodeBytes)
	}
}

func CreateClient(conn net.Conn) *Client {
	client := &Client{}
	client.clientConn = conn
	reader := bufio.NewReader(client.clientConn)
	client.responseChan = make(chan *http.Response, 1024)
	client.transponder = CreateTransponder(client)
	client.bufferReader = reader
	go client.repeatResponse()

	return client
}
